deferred class CD_FILLED_AREAS
-- It is an area filled with the foreground color, but it depends on the 
-- current interior style. The "solid" style depends only on the foreground 
-- color. The "hatch" and "stipple" style depend on the foreground color, 
-- background color and on the back opacity attribute. The hatch lines drawn 
-- with this style do not depend on the other line attributes. The "pattern" 
-- style depends only on global canvas attributes.
--
-- The filled area includes the line at the edge of the area. So if you draw a 
-- filled rectangle, sector or polygon on top of a non filled one using the 
-- same coordinates, no style and 1 pixel width, the non filled primitive 
-- should be obscured by the filled primitive. But depending on the driver 
-- implementation some pixels at the edges may be not included. IMPORTANT: In 
-- the Postscript and PDF drivers the line at the edge is not included at all.
-- If either the background or the foreground color are modified, the hatched 
-- and monochromatic fillings must be modified again in order to be updated.
--
-- Note that when a Filling Attribute is modified, the active filling style is 
-- now that of the modified attribute (hatch, stipple or pattern). Notice that 
-- this is not true for the clipping area. When the clipping area is modified, 
-- the clipping is only affected if it is active.

inherit
	CANVAS_DRAW

feature {ANY}

	draws_box (xmin, xmax, ymin, ymax: INTEGER)
		-- Fills a rectangle according to the current interior style. All points 
		-- in the interval x_min <= x <= x_max, y_min <= y <= y_max will be 
		-- painted. When the interior style "hollow" is defined, the function 
		-- behaves like its equivalent "draws_rect".
		do
			int_canvas_box (cnvs, xmin, xmax, ymin, ymax)
		end

	draws_box_real (xmin, xmax, ymin, ymax: REAL_64)
		-- As "draws_box" but with REAL_64 coordinates.
		do
			int_canvas_c_double_box (cnvs, xmin, xmax, ymin, ymax)
		end

	wd_draws_box (xmin, xmax, ymin, ymax: REAL_64)
		-- As "draws_box" but with World coordinates.
		do
			int_wd_canvas_box (cnvs, xmin, xmax, ymin, ymax)
		end

	draws_sector (xc, yc, w, h: INTEGER; angle1, angle2: REAL_64)
		-- Fills the arc of an ellipse aligned with the axis, according to the 
		-- current interior style, in the shape of a pie.
		--
		-- The coordinate (xc,yc) defines the center of the ellipse. Dimensions w 
		-- and h define the elliptic axes X and Y, respectively.
		--
		-- Angles angle1 and angle2 are in degrees and oriented 
		-- counter-clockwise. They define the arc start and end, but they are not 
		-- the angle relative to the center, except when w==h and the ellipse is 
		-- reduced to a circle. The arc starts at the point 
		-- (xc+(w/2)*cos(angle1), yc+(h/2)*sin(angle1)) and ends at 
		-- (xc+(w/2)*cos(angle2), yc+(h/2)*sin(angle2)). A complete ellipse can 
		-- be drawn using 0 and 360 as the angles. If angle2 is less than angle1 
		-- it will be increased by 360 until it is greater than angle1.
		--
		-- The angles are specified so if the size of the ellipse (w x h) is 
		-- changed, its shape is preserved. So the angles relative to the center 
		-- are dependent from the ellipse size. The actual angle can be obtained 
		-- using rangle = atan2((h/2)*sin(angle), (w/2)*cos(angle)).
		--
		-- When the interior style "hollow" is defined, the function behaves 
		-- like its equivalent "draws_arc", plus two lines connecting to the 
		-- center.	
		do
			int_canvas_sector (cnvs, xc, yc, w, h, angle1, angle2)
		end

	draws_sector_real (xc, yc, w, h, angle1, angle2: REAL_64)
		-- As "draws_sector" but with REAL_64 coordinates.
		do
			int_canvas_c_double_sector (cnvs, xc, yc, w, h, angle1, angle2)
		end

	wd_draws_sector (xc, yc, w, h, angle1, angle2: REAL_64)
		-- As "draws_sector" but with World coordinates.
		do
			int_wd_canvas_sector (cnvs, xc, yc, w, h, angle1, angle2)
		end

	draws_chord (xc, yc, w, h: INTEGER; angle1, angle2: REAL_64)
		-- Fills the arc of an ellipse aligned with the axis, according to the 
		-- current interior style, the start and end points of the arc are 
		-- connected. The parameters are the same as the "draws_sector".
		--
		-- When the interior style "hollow" is defined, the function behaves 
		-- like its equivalent "draws_arc", plus a line connecting the arc start 
		-- and end points.
		do
			int_canvas_chord (cnvs, xc, yc, w, h, angle1, angle2)
		end

	draws_chord_real (xc, yc, w, h, angle1, angle2: REAL_64)
		-- As "draws_chord" but with REAL_64 coordinates.
		do
			int_canvas_c_double_chord (cnvs, xc, yc, w, h, angle1, angle2)
		end

	wd_draws_chord (xc, yc, w, h, angle1, angle2: REAL_64)
		-- As "draws_chord" but with World coordinates.
		do
			int_wd_canvas_chord (cnvs, xc, yc, w, h, angle1, angle2)
		end

	-- Attributes

	set_back_opacity (opacity: STRING)
		-- Configures the background opacity to filling primitives based on the 
		-- foreground and background colors. Note that only when interior style 
		-- is "hatch" or "stipple" that back opacity is used. Values: 
		-- CD_TRANSPARENT or CD_OPAQUE. If it is opaque the primitive will erase 
		-- whatever is in the background with the background color. If it is 
		-- transparent, only the foreground color is painted.
		-- Default value: CD_TRANSPARENT.
		-- In some drivers is always opaque.
		require
			is_valid_back_opacity (opacity)
		local
			i: INTEGER
		do
			if opacity.is_equal("CD_OPAQUE") then
				i := int_canvas_back_opacity (cnvs, 0)
			elseif opacity.is_equal("CD_TRANSPARENT") then
				i := int_canvas_back_opacity (cnvs, 1)
			end
		end

	get_back_opacity: STRING
		local
			i: INTEGER
		do
			i := int_canvas_back_opacity (cnvs, -1)

			if i.is_equal(0) then
				Result := "CD_OPAQUE"
			elseif i.is_equal(1) then
				Result := "CD_TRANSPARENT"
			else
				Result := "CD_OPAQUE"
			end
		end

	set_back_opacity_opaque
		local
			i: INTEGER
		do
			i := int_canvas_back_opacity (cnvs, 0)
		end

	set_back_opacity_transparent
		local
			i: INTEGER
		do
			i := int_canvas_back_opacity (cnvs, 1)
		end

	set_fill_mode (mode: STRING)
		-- Selects a predefined polygon fill rule (CD_EVENODD or CD_WINDING).
		-- Default value: CD_EVENODD.
		require
			is_valid_fill_mode (mode)
		local
			i: INTEGER
		do
			if mode.is_equal("CD_EVENODD") then
				i := int_canvas_back_opacity (cnvs, 0)
			elseif mode.is_equal("CD_WINDING") then
				i := int_canvas_back_opacity (cnvs, 1)
			end
		end

	get_fill_mode: STRING
		local
			i: INTEGER
		do
			i := int_canvas_fill_mode (cnvs, -1)

			if i.is_equal(0) then
				Result := "CD_EVENODD"
			elseif i.is_equal(1) then
				Result := "CD_WINDING"
			else
				Result := "CD_EVENODD"
			end
		end

	set_fill_mode_even_odd
		local
			i: INTEGER
		do
			i := int_canvas_back_opacity (cnvs, 0)
		end

	set_fill_mode_winding
		local
			i: INTEGER
		do
			i := int_canvas_back_opacity (cnvs, 1)
		end

	set_interior_style (style: STRING)
		-- Configures the current style for the area filling primitives: 
		-- CD_SOLID, CD_HOLLOW, CD_HATCH, CD_STIPPLE or CD_PATTERN. Note that 
		-- only CD_HATCH and CD_STIPPLE are affected by the backopacity.
		-- Default value: CD_SOLID.
		--
		-- If a stipple or a pattern were not defined, when they are selected the 
		-- state of the attribute is not changed.
		--
		-- When the style CD_HOLLOW is defined, functions "draws_box" and 
		-- "draws_sector" behave as their equivalent "draws_rect" and 
		-- "draws_arc", and the polygons with style "fill" behave like 
		-- "closed_lines". 	
		require
			is_valid_interior_style(style)
		local
			i: INTEGER
		do
			if style.is_equal("CD_SOLID") then
				i := int_canvas_interior_style (cnvs, 0)
			elseif style.is_equal("CD_HATCH") then
				i := int_canvas_interior_style (cnvs, 1)
			elseif style.is_equal("CD_STIPPLE") then
				i := int_canvas_interior_style (cnvs, 2)
			elseif style.is_equal("CD_PATTERN") then
				i := int_canvas_interior_style (cnvs, 3)
			elseif style.is_equal("CD_HOLLOW") then
				i := int_canvas_interior_style (cnvs, 4)
			end
		end

	get_interior_style: STRING
		local
			i: INTEGER
		do
			i := int_canvas_interior_style (cnvs, -1)

			if i.is_equal(0) then
				Result := "CD_SOLID"
			elseif i.is_equal(1) then
				Result := "CD_HATCH"
			elseif i.is_equal(2) then
				Result := "CD_STIPPLE"
			elseif i.is_equal(3) then
				Result := "CD_PATTERN"
			elseif i.is_equal(4) then
				Result := "CD_HOLLOW"
			else
				Result := "CD_SOLID"
			end
		end

	set_interior_style_solid
		local
			i: INTEGER
		do
			i := int_canvas_interior_style (cnvs, 0)
		end

	set_interior_style_hatch
		local
			i: INTEGER
		do
			i := int_canvas_interior_style (cnvs, 1)
		end

	set_interior_style_stipple
		local
			i: INTEGER
		do
			i := int_canvas_interior_style (cnvs, 2)
		end

	set_interior_style_pattern
		local
			i: INTEGER
		do
			i := int_canvas_interior_style (cnvs, 3)
		end

	set_interior_style_hollow
		local
			i: INTEGER
		do
			i := int_canvas_interior_style (cnvs, 4)
		end

	set_hatch (style: STRING)
		-- Selects a predefined hatch style (CD_HORIZONTAL, CD_VERTICAL, 
		-- CD_FDIAGONAL, CD_BDIAGONAL, CD_CROSS or CD_DIAGCROSS) and sets the 
		-- interior style to CD_HATCH. The lines are drawn with the foreground 
		-- color, and the background is drawn with the background color if back 
		-- opacity is opaque.
		-- Default value: CD_HORIZONTAL.
		-- The foreground and background colors must be set before setting the 
		-- style. In some drivers is always opaque.
		require
			is_valid_hatch(style)
		local
			i: INTEGER
		do
			if style.is_equal("CD_HORIZONTAL") then
				i := int_canvas_hatch (cnvs, 0)
			elseif style.is_equal("CD_VERTICAL") then
				i := int_canvas_hatch (cnvs, 1)
			elseif style.is_equal("CD_FDIAGONAL") then
				i := int_canvas_hatch (cnvs, 2)
			elseif style.is_equal("CD_BDIAGONAL") then
				i := int_canvas_hatch (cnvs, 3)
			elseif style.is_equal("CD_CROSS") then
				i := int_canvas_hatch (cnvs, 4)
			elseif style.is_equal("CD_DIAGCROSS") then
				i := int_canvas_hatch (cnvs, 5)
			end
		end

	get_hatch: STRING
		local
			i: INTEGER
		do
			i := int_canvas_hatch (cnvs, -1)

			if i.is_equal(0) then
				Result := "CD_HORIZONTAL"
			elseif i.is_equal(1) then
				Result := "CD_VERTICAL"
			elseif i.is_equal(2) then
				Result := "CD_FDIAGONAL"
			elseif i.is_equal(3) then
				Result := "CD_BDIAGONAL"
			elseif i.is_equal(4) then
				Result := "CD_CROSS"
			elseif i.is_equal(5) then
				Result := "CD_DIAGCROSS"
			else
				Result := "CD_HORIZONTAL"
			end
		end

	set_hatch_horizontal
		local
			i: INTEGER
		do
			i := int_canvas_hatch (cnvs, 0)
		end

	set_hatch_vertical
		local
			i: INTEGER
		do
			i := int_canvas_hatch (cnvs, 1)
		end

	set_hatch_forward_diagonal
		local
			i: INTEGER
		do
			i := int_canvas_hatch (cnvs, 2)
		end

	set_hatch_backward_diagonal
		local
			i: INTEGER
		do
			i := int_canvas_hatch (cnvs, 3)
		end

	set_hatch_cross
		local
			i: INTEGER
		do
			i := int_canvas_hatch (cnvs, 4)
		end

	set_hatch_diagonal_cross
		local
			i: INTEGER
		do
			i := int_canvas_hatch (cnvs, 5)
		end

	set_stipple (marks: ARRAY2[INTEGER])
		-- Defines a wxh matrix of zeros (0) and ones (1). The zeros are mapped 
		-- to the background color or are transparent, according to the 
		-- background opacity attribute. The ones are mapped to the foreground 
		-- color. The function sets the interior style to "sttiple". It does not 
		-- need to be stored by the application, as it is internally replicated 
		-- by the library. In some drivers is always opaque. The foreground and 
		-- background colors must be set before setting the style.
		do
			int_canvas_stipple (cnvs, marks.width, marks.height,
			                    convert_array2(marks))
		end

	set_wd_stipple (marks: ARRAY2[INTEGER]; width_mm, height_mm: REAL_64)
		-- Allows specifying the stipple in world coordinates. Another stipple 
		-- will be created with the size in pixels corresponding to the specified 
		-- size in millimeters. The new size in pixels will be an integer factor 
		-- of the original size that is closets to the size in millimeters. The 
		-- use of this function may produce very large or very small stipples.
		do
			int_wd_canvas_stipple (cnvs, marks.width, marks.height,
			                       convert_array2(marks),
			                       width_mm, height_mm)
		end

	get_stipple: detachable ARRAY2[INTEGER]
		-- Returns the current stipple. Returns Void if no 
		-- stipple was defined.
		local
			w, h: INTEGER
			p: POINTER
		do
			p := int_canvas_get_stipple (cnvs, $w, $h)

			if p /= default_pointer then
				Result := get_array2(p, w, h)
			end
		end

	set_pattern (colors: ARRAY2[INTEGER])
		-- Defines a new wxh color matrix and sets the interior style to 
		-- "pattern". It does not need to be stored by the application, as it is 
		-- internally replicated by the library.
		do
			int_canvas_pattern (cnvs, colors.width, colors.height,
			                    convert_colors_array2(colors))
		end

	set_wd_pattern (colors: ARRAY2[INTEGER]; width_mm, height_mm: REAL_64)
		-- Allows specifying the pattern in world coordinates. Another pattern 
		-- will be created with the size in pixels corresponding to the specified 
		-- size in millimeters. The new size in pixels will be an integer factor 
		-- of the original size that is closets to the size in millimeters. The 
		-- use of this function may produce very large or very small patterns.
		do
			int_wd_canvas_pattern (cnvs, colors.width, colors.height,
			                       convert_colors_array2(colors),
			                       width_mm, height_mm)
		end

	get_pattern: detachable ARRAY2[INTEGER]
		-- Returns the current pattern and its dimensions. Returns Void if no 
		-- pattern was defined.
		local
			w, h: INTEGER
			p: POINTER
		do
			p := int_canvas_get_pattern (cnvs, $w, $h)

			if p /= default_pointer then
				Result := get_colors_array2(p, w, h)
			end
		end


	-- Validations

	is_valid_back_opacity (opacity: STRING): BOOLEAN
		do
			if opacity.is_equal("CD_OPAQUE") or
				opacity.is_equal("CD_TRANSPARENT") then
				Result := True
			else
				Result := False
			end
		end

	is_valid_fill_mode (mode: STRING): BOOLEAN
		do
			if mode.is_equal("CD_EVENODD") or
				mode.is_equal("CD_WINDING") then
				Result := True
			else
				Result := False
			end
		end

	is_valid_interior_style (style: STRING): BOOLEAN
		do
			if style.is_equal("CD_SOLID") or
				style.is_equal("CD_HOLLOW") or
				style.is_equal("CD_HATCH") or
				style.is_equal("CD_STIPPLE") or
				style.is_equal("CD_PATTERN") then
				Result := True
			else
				Result := False
			end
		end

	is_valid_hatch (style: STRING): BOOLEAN
		do
			if style.is_equal("CD_HORIZONTAL") or
				style.is_equal("CD_VERTICAL") or
				style.is_equal("CD_FDIAGONAL") or
				style.is_equal("CD_BDIAGONAL") or
				style.is_equal("CD_CROSS") or
				style.is_equal("CD_DIAGCROSS") then
				Result := True
			else
				Result := False
			end
		end

feature {NONE}
	
	-- Convertions

	convert_array2 (matrix: ARRAY2[INTEGER]): POINTER
		local
			w, h, v: INTEGER;
			arg: ARRAY[CHARACTER_8]
			i, x, y: INTEGER
		do
			h := matrix.height
			w := matrix.width

			create arg.make_filled(' ', 1, w*h + 1)
			i := 0
			
			from
				x := 0
         until
				x = w
         loop
				from
					y := 0
				until
					y = w
				loop
					v := matrix.item(x, y)
					arg.put(v.to_character_8, i)
					i := i + 1
					y := y + 1
				end

				x := x + 1
         end

			Result := get_pointer(arg.to_c)
		end

	get_array2 (array: POINTER; w, h: INTEGER): ARRAY2[INTEGER]
		local
			i, x, y: INTEGER
			arg: MANAGED_POINTER
			marks: ARRAY2[INTEGER]
		do
			create marks.make_filled (0, h, w)
			create arg.make_from_pointer(array, w*h)

			i := 0

			from
				x := 0
         until
				x = w
         loop
				from
					y := 0
				until
					y = h
				loop
					marks.put(arg.read_integer_32(i), y, x)
					
					i := i + 1
					y := y + 1
				end

				x := x + 1
         end

			Result := marks
		end

	convert_colors_array2 (matrix: ARRAY2[INTEGER]): POINTER
		-- Revise GOBO
		local
			x, y, i, w, h: INTEGER
			marks: ARRAY[INTEGER_8]
		do
			w := matrix.width
			h := matrix.height
			
			create marks.make_filled ((0).to_integer_8, 1, w*h + 1)

			i := 1

			from
				x := 1
         until
				x = w
         loop
				from
					y := 1
				until
					y = h
				loop
					marks.put(matrix.item(y, x).to_integer_8, i)
					
					i := i + 1
					y := y + 1
				end

				x := x + 1
         end

			Result := get_pointer(marks.to_c)
		end

	get_colors_array2 (array: POINTER; w, h: INTEGER): ARRAY2[INTEGER]
		local
			x, y: INTEGER
			i, v: INTEGER
			arg: MANAGED_POINTER
			marks: ARRAY2[INTEGER]
		do
			create marks.make_filled (0, h, w)
			create arg.make_from_pointer(array, w*h)

			i := 0

			from
				x := 0
         until
				x = w
         loop
				from
					y := 0
				until
					y = h
				loop
					v := arg.read_integer_32(i)
					marks.put(v, y, x)
					
					i := i + 1
					y := y + 1
				end

				x := x + 1
         end

			Result := marks
		end

	-- Internals

	int_canvas_box (wgt: POINTER; xmin, xmax, ymin, ymax: INTEGER)
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"cdCanvasBox ($wgt, $xmin, $xmax, $ymin, $ymax);"
      end

	int_canvas_c_double_box (wgt: POINTER; xmin, xmax, ymin, ymax: REAL_64)
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"cdfCanvasBox ($wgt, $xmin, $xmax, $ymin, $ymax);"
      end

	int_wd_canvas_box (wgt: POINTER; xmin, xmax, ymin, ymax: REAL_64)
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"wdCanvasBox ($wgt, $xmin, $xmax, $ymin, $ymax);"
      end

	int_canvas_sector (wgt: POINTER; xc, yc, w, h: INTEGER; a1, a2: REAL_64)
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"cdCanvasSector ($wgt, $xc, $yc, $w, $h, $a1, $a2);"
      end

	int_canvas_c_double_sector (wgt: POINTER; xc, yc, w, h, a1, a2: REAL_64)
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"cdfCanvasSector ($wgt, $xc, $yc, $w, $h, $a1, $a2);"
      end

	int_wd_canvas_sector (wgt: POINTER; xc, yc, w, h, a1, a2: REAL_64)
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"wdCanvasSector ($wgt, $xc, $yc, $w, $h, $a1, $a2);"
      end

	int_canvas_chord (wgt: POINTER; xc, yc, w, h: INTEGER; a1, a2: REAL_64)
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"cdCanvasChord ($wgt, $xc, $yc, $w, $h, $a1, $a2);"
      end

	int_canvas_c_double_chord (wgt: POINTER; xc, yc, w, h, a1, a2: REAL_64)
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"cdfCanvasChord ($wgt, $xc, $yc, $w, $h, $a1, $a2);"
      end

	int_wd_canvas_chord (wgt: POINTER; xc, yc, w, h, a1, a2: REAL_64)
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"wdCanvasChord ($wgt, $xc, $yc, $w, $h, $a1, $a2);"
      end

	int_canvas_back_opacity (wgt: POINTER; o: INTEGER): INTEGER
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"return cdCanvasBackOpacity ($wgt, $o);"
      end

	int_canvas_fill_mode (wgt: POINTER; m: INTEGER): INTEGER
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"return cdCanvasFillMode ($wgt, $m);"
      end

	int_canvas_interior_style (wgt: POINTER; s: INTEGER): INTEGER
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"return cdCanvasInteriorStyle ($wgt, $s);"
      end

	int_canvas_hatch (wgt: POINTER; s: INTEGER): INTEGER
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"return cdCanvasHatch ($wgt, $s);"
      end

	int_canvas_stipple (wgt: POINTER; w, h: INTEGER; fgfb: POINTER)
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"cdCanvasStipple ($wgt, $w, $h, $fgfb);"
      end

	int_canvas_stipple_imimage (wgt, im: POINTER)
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"cdCanvasStippleImImage ($wgt, $im);"
      end

	int_wd_canvas_stipple (wgt: POINTER; w, h: INTEGER; fgfb: POINTER; w_mm, h_mm: REAL_64)
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"wdCanvasStipple ($wgt, $w, $h, $fgfb, $w_mm, $h_mm);"
      end

	int_canvas_get_stipple (wgt, w, h: POINTER): POINTER
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"return cdCanvasGetStipple ($wgt, $w, $h);"
      end

	int_canvas_pattern (wgt: POINTER; w, h: INTEGER; color: POINTER)
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"cdCanvasPattern ($wgt, $w, $h, $color);"
      end

	int_canvas_pattern_imimage (wgt, im: POINTER)
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"cdCanvasPatternImImage ($wgt, $im);"
      end

	int_wd_canvas_pattern (wgt: POINTER; w, h: INTEGER; color: POINTER; w_mm, h_mm: REAL_64)
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"wdCanvasPattern ($wgt, $w, $h, $color, $w_mm, $h_mm);"
      end

	int_canvas_get_pattern (wgt, w, h: POINTER): POINTER
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"return cdCanvasGetPattern ($wgt, $w, $h);"
      end

end

-- The MIT License (MIT)

-- Copyright (c) 2016, 2019, 2020 by German A. Arias

-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in 
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.

